﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.VisualStudio.SharePoint.Commands;

namespace SPVSX.DeploymentExtensions.SharePointCommands
{
    /// <summary>
    /// Custom commands for deployment-related extensions.
    /// 
    /// This code is a WIP and is in need of improved commenting, exception handling, and potentially
    /// factoring.  Please be nice.
    /// 
    /// Though this code is Open Source, in good faith it is requested that you consult the original author(s)
    /// before changing or re-using it for any public endeavour intended to provide similar functionality, or
    /// to fix simple bugs.  In other words, if you want to create SPVSX2, please let us know first.
    /// </summary>
    /// <remarks>@author Matt Smith, http://blog.mattsmith.co.nz</remarks>
    internal class DeploymentExtensionCommands
    {
        // Determines whether the specified solution has been deployed to the local SharePoint server.
        [SharePointCommand("SPVSX.Commands.IsSolutionDeployed")]
        private bool IsSolutionDeployed(ISharePointCommandContext context, string solutionName)
        {
            SPSolution solution = SPFarm.Local.Solutions[solutionName];
            return solution != null;
        }

        // Upgrades the specified solution to the local SharePoint server.
        [SharePointCommand("SPVSX.Commands.UpgradeSolution")]
        private void UpgradeSolution(ISharePointCommandContext context, string fullWspPath)
        {
            SPSolution solution = SPFarm.Local.Solutions[Path.GetFileName(fullWspPath)];
            
            if (solution == null)
            {
                throw new Exception("The solution has not been deployed.");
            }

            solution.Upgrade(fullWspPath);
        }

        // Retrieves the application pool name of a given url.
        [SharePointCommand("SPVSX.Commands.GetApplicationPoolName")]
        private string GetApplicationPoolName(ISharePointCommandContext context, string url)
        {
            string name = null;
            try
            {
                using (SPSite site = new SPSite(url))
                {
                    name = site.WebApplication.ApplicationPool.Name;
                }
            }
            catch
            {
            }

            return name;
        }

        // Retrieves a unique list of all application pools used by SharePoint.
        [SharePointCommand("SPVSX.Commands.GetAllApplicationPoolNames")]
        private string[] GetAllApplicationPoolNames(ISharePointCommandContext context)
        {
            List<string> names = new List<string>();

            foreach (SPWebApplication app in SPWebService.ContentService.WebApplications.Union(SPWebService.AdministrationService.WebApplications))
            {
                if (! names.Contains(app.ApplicationPool.Name))
                {
                    names.Add(app.ApplicationPool.Name);
                }
            }
            
            return names.ToArray();
        }

        // Retrieves the physical path of a given web application.
        [SharePointCommand("SPVSX.Commands.GetWebApplicationDefaultPhysicalPath")]
        private string GetWebApplicationDefaultPhysicalPath(ISharePointCommandContext context, string url)
        {        
            string name = null;
            try
            {
                using (SPSite site = new SPSite(url))
                {
                    SPWebApplication app = site.WebApplication;

                    if (app.IisSettings.ContainsKey(SPUrlZone.Default))
                    {
                        name = app.IisSettings[SPUrlZone.Default].Path.FullName;
                    }
                    else
                    {
                        foreach (SPUrlZone zone in app.IisSettings.Keys)
                        {
                            name = app.IisSettings[zone].Path.FullName;
                            break;
                        }
                    }
                }
            }
            catch
            {
            }

            return name;
        }
    }
}